package com.joyplus.report.business.service;

import com.joyplus.report.business.dao.MdCampaignSupplementDao;
import com.joyplus.report.business.document.C2sDistributionMachineStatisticsFreDocument;
import com.joyplus.report.business.document.C2sDistributionMachineStatisticsHourDocument;
import com.joyplus.report.business.document.C2sDistributionMachineStatisticsLocationFullDocument;
import com.joyplus.report.business.document.DistributionPvUvStatisticsLocationDocument;
import com.joyplus.report.business.document.OptimizationTaskFullFerStatisticsDocument;
import com.joyplus.report.business.document.OptimizationTaskStatisticsDocument;
import com.joyplus.report.business.document.OptimizationTaskStatisticsFreDocument;
import com.joyplus.report.business.document.OptimizationTaskStatisticsHourDocument;
import com.joyplus.report.business.document.OptimizationTaskStatisticsLocationDocument;
import com.joyplus.report.business.document.OptimizationTaskStatisticsLocationFullDocument;
import com.joyplus.report.business.domain.FullFreModel;
import com.joyplus.report.business.domain.MdCampaignSupplement;
import com.joyplus.report.business.domain.PvUvModel;
import com.joyplus.report.business.domain.StatisticsFre;
import com.joyplus.report.common.service.BaseService;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.Fields;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

/**
 * Created by  2018/6/14.
 */
@Service
public class OptimizationTaskStatisticsService extends
    BaseService<MdCampaignSupplementDao, MdCampaignSupplement> {

  @Resource
  private MdCampaignSupplementDao mdCampaignSupplementDao;

  @Autowired
  MongoTemplate mongoTemplate;

  /**
   * 获取计划的分时
   */
  public List getTaskStatisticsByHour(String[] id, String stratDate, String endDate) {

    Criteria criteria = new Criteria().andOperator(Criteria.where("campaign_id").in(id),
        Criteria.where("task_date").gte(stratDate), Criteria.where("task_date").lte(endDate));
    Aggregation customerAgg1 = Aggregation.newAggregation(
        Aggregation.match(criteria),
        Aggregation.group(Fields.fields("task_hour", "campaign_id", "task_date")).sum("pv").as("pv")
            .sum("uv")
            .as("uv"),
        Aggregation.project(Fields.fields("task_hour", "campaign_id", "pv", "uv", "task_date")),
        Aggregation.sort(new Sort(new Order(Direction.ASC, "task_hour")))
    );
    HashMap<String, OptimizationTaskStatisticsHourDocument> map = new HashMap<>();
    List<PvUvModel> PvUvModel = new ArrayList<>();
    PvUvModel pvUvModelBean = new PvUvModel();

    System.out.println(customerAgg1.toString());
    AggregationResults<OptimizationTaskStatisticsHourDocument> document = mongoTemplate
        .aggregate(customerAgg1, "optimization_task_statistics_hour",
            OptimizationTaskStatisticsHourDocument.class);

    List<OptimizationTaskStatisticsHourDocument> mappedResults = document.getMappedResults();

    for (OptimizationTaskStatisticsHourDocument doc : mappedResults
        ) {
      pvUvModelBean = new PvUvModel();
      if (map.get(doc.getCampaignId() + doc.getTaskDate()) == null) {

        MdCampaignSupplement byId = mdCampaignSupplementDao
            .getById(Integer.parseInt(doc.getCampaignId()));
        doc.setCampaignName(byId.getCampaignName());
        PvUvModel = new ArrayList<>();
        pvUvModelBean.setTaskHour(doc.getTaskHour());
        pvUvModelBean.setUv(doc.getUv());
        pvUvModelBean.setPv(doc.getPv());
        PvUvModel.add(pvUvModelBean);
        doc.setList(PvUvModel);
        map.put(doc.getCampaignId() + doc.getTaskDate(), doc);
      } else {
        OptimizationTaskStatisticsHourDocument hourDocument = map
            .get(doc.getCampaignId() + doc.getTaskDate());
        pvUvModelBean.setTaskHour(doc.getTaskHour());
        pvUvModelBean.setUv(doc.getUv());
        pvUvModelBean.setPv(doc.getPv());
        hourDocument.getList().add(pvUvModelBean);
        map.put(doc.getCampaignId() + doc.getTaskDate(), hourDocument);
      }
    }

    Iterator<Entry<String, OptimizationTaskStatisticsHourDocument>> iterator = map.entrySet()
        .iterator();
    mappedResults = new ArrayList<>();
    while (iterator.hasNext()) {
      mappedResults.add(iterator.next().getValue());
    }

    return mappedResults;
  }

  /**
   * 获取计划的频次
   */
  public List getTaskStatisticsByFre(String[] id, String stratDate) {
    Query query = new Query();
    Criteria criteria = new Criteria().andOperator(
        Criteria.where("campaign_id").in(id),
        Criteria.where("task_date").is(stratDate));
    query.addCriteria(criteria);
    query.with(new Sort(Direction.ASC, "fre"));
    Aggregation aggregation = Aggregation.newAggregation(
        Aggregation.match(criteria),
        Aggregation.group(Fields.fields("campaign_id", "freq", "task_date")).sum("pv").as("pv")
            .sum("count").as("count"),
        Aggregation.project(Fields.fields("campaign_id", "freq", "task_date", "pv", "count")),
        Aggregation.sort(new Sort(new Order(Direction.ASC, "freq")))
    );
    System.out.println(aggregation.toString());
    AggregationResults<OptimizationTaskStatisticsFreDocument> aggregate = mongoTemplate
        .aggregate(aggregation, "optimization_task_statistics",
            OptimizationTaskStatisticsFreDocument.class);
    List<OptimizationTaskStatisticsFreDocument> documents = aggregate.getMappedResults();
    List<StatisticsFre> list = new ArrayList<>();
    StatisticsFre statisticsFre = new StatisticsFre();
    HashMap<String, StatisticsFre> map = new HashMap<>();
    for (OptimizationTaskStatisticsFreDocument doc : documents
        ) {
      try {
        if (map.get(doc.getCampaign_id()) != null) {
          statisticsFre = map.get(doc.getCampaign_id());
          statisticsFre.setCampaignId(doc.getCampaign_id());
          statisticsFre.setTaskDate(doc.getTask_date());
          if (doc.getFre() >= 12) {
            int count = (int) doc.getCount() + statisticsFre.getN12();
            statisticsFre.setN12(count);
            statisticsFre.setPv12(doc.getPv() + statisticsFre.getPv12());
          } else {
            Method method = statisticsFre.getClass()
                .getDeclaredMethod("setN" + (int) doc.getFre(), Integer.class);
            method.invoke(statisticsFre, (int) doc.getCount());

            Method method1 = statisticsFre.getClass()
                .getDeclaredMethod("setPv" + (int) doc.getFre(),
                    Integer.class);
            method1.invoke(statisticsFre, (int) doc.getPv());
          }
        } else {
          statisticsFre = new StatisticsFre();
          statisticsFre.setCampaignId(doc.getCampaign_id());
          if (doc.getFre() >= 12) {
            int count = (int) doc.getCount();
            statisticsFre.setN12(count);
            statisticsFre.setPv12(doc.getPv());
          } else {
            Method method = statisticsFre.getClass()
                .getDeclaredMethod("setN" + (int) doc.getFre(), Integer.class);
            method.invoke(statisticsFre, (int) doc.getCount());
            Method method1 = statisticsFre.getClass()
                .getDeclaredMethod("setPv" + (int) doc.getFre(),
                    Integer.class);
            method1.invoke(statisticsFre, (int) doc.getPv());
          }
        }
        map.put(doc.getCampaign_id(), statisticsFre);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }

    Iterator<Entry<String, StatisticsFre>> iterator = map.entrySet()
        .iterator();
    while (iterator.hasNext()) {
      statisticsFre = iterator.next().getValue();
      MdCampaignSupplement byId = mdCampaignSupplementDao
          .getById(Integer.parseInt(statisticsFre.getCampaignId()));
      statisticsFre.setCampaignName(byId.getCampaignName());
      list.add(statisticsFre);
    }
    return list;
  }

  /**
   * 获取计划的地域
   */

  public List getTaskStatisticsByLocation(String[] id, String stratDate, String endDate) {
    Criteria criteria = new Criteria().andOperator(
        Criteria.where("campaign_id").in(id));
    Aggregation aggregation = Aggregation.newAggregation(
        Aggregation.match(criteria),
        Aggregation.group(Fields.fields("campaign_id", "province")).sum("pv").as("pv")
            .sum("uv").as("uv"),
        Aggregation.project(Fields.fields("campaign_id", "province", "pv", "uv"))
    );
    AggregationResults<OptimizationTaskStatisticsLocationDocument> statisticsLocation = mongoTemplate
        .aggregate(aggregation, "optimization_task_statistics_location",
            OptimizationTaskStatisticsLocationDocument.class);
    List<OptimizationTaskStatisticsLocationDocument> results = statisticsLocation
        .getMappedResults();
    System.out.println(aggregation.toString());
    return results;
  }

  /**
   * 获取计划的地域
   */

  public List getTaskStatisticsByLocationAndDate(String[] id, String stratDate, String endDate) {
    Criteria criteria = new Criteria().andOperator(
        Criteria.where("campaign_id").in(id),
        Criteria.where("task_date").lte(endDate).gte(stratDate));
    Aggregation aggregation = Aggregation.newAggregation(
        Aggregation.match(criteria),
        Aggregation.group(Fields.fields("campaign_id", "province")).sum("pv").as("pv")
            .sum("uv").as("uv"),
        Aggregation.project(Fields.fields("campaign_id", "province", "pv", "uv"))
    );
    AggregationResults<OptimizationTaskStatisticsLocationDocument> statisticsLocation = mongoTemplate
        .aggregate(aggregation, "optimization_task_statistics_location",
            OptimizationTaskStatisticsLocationDocument.class);
    List<OptimizationTaskStatisticsLocationDocument> results = statisticsLocation
        .getMappedResults();
    System.out.println(aggregation.toString());
    return results;
  }


  /**
   * 获取计划
   */
  public List getTaskStatisticsByDate(String[] id, String stratDate, String endDate) {

    Criteria criteria = new Criteria().andOperator(
        Criteria.where("campaign_id").in(id), Criteria.where("task_date").lte(endDate).gte(stratDate));
    Aggregation aggregation = Aggregation.newAggregation(
        Aggregation.match(criteria),
        Aggregation.group(Fields.fields("campaign_id", "task_date")).sum("pv").as("pv")
            .sum("count").as("uv"),
        Aggregation.project(Fields.fields("campaign_id", "task_date", "pv", "uv")),
        Aggregation.sort(new Sort(new Order(Direction.ASC, "task_date")))
    );
    System.out.println(aggregation.toString());
    AggregationResults<OptimizationTaskStatisticsDocument> aggregate = mongoTemplate
        .aggregate(aggregation, "optimization_task_statistics",
            OptimizationTaskStatisticsDocument.class);
    List<OptimizationTaskStatisticsDocument> documents = aggregate.getMappedResults();
    HashMap<String, OptimizationTaskStatisticsDocument> map = new HashMap<>();
    List<PvUvModel> PvUvModel = new ArrayList<>();
    PvUvModel pvUvModelBean = new PvUvModel();
    for (OptimizationTaskStatisticsDocument doc : documents
        ) {
      pvUvModelBean = new PvUvModel();
      if (map.get(doc.getCampaign_id()) == null) {
        MdCampaignSupplement byId = mdCampaignSupplementDao
            .getById(Integer.parseInt(doc.getCampaign_id()));
        doc.setCampaignName(byId.getCampaignName());
        PvUvModel = new ArrayList<>();
        pvUvModelBean.setTaskDate(doc.getTask_date());
        pvUvModelBean.setUv(doc.getUv());
        pvUvModelBean.setPv(doc.getPv());
        PvUvModel.add(pvUvModelBean);
        doc.setList(PvUvModel);
        map.put(doc.getCampaign_id(), doc);
      } else {
        OptimizationTaskStatisticsDocument hourDocument = map
            .get(doc.getCampaign_id());
        pvUvModelBean.setTaskDate(doc.getTask_date());
        pvUvModelBean.setUv(doc.getUv());
        pvUvModelBean.setPv(doc.getPv());
        hourDocument.getList().add(pvUvModelBean);
        map.put(doc.getCampaign_id(), hourDocument);
      }
    }

    Iterator<Entry<String, OptimizationTaskStatisticsDocument>> iterator = map.entrySet()
        .iterator();
    documents = new ArrayList<>();
    while (iterator.hasNext()) {
      documents.add(iterator.next().getValue());
    }
    return documents;
  }

  public List getTaskStatisticsByProvince(String[] id, String stratDate, String endDate,
      String province) {
    Criteria criteria = new Criteria().andOperator(
        Criteria.where("campaign_id").in(id),
        Criteria.where("province").is(province));
    Aggregation aggregation = Aggregation.newAggregation(
        Aggregation.match(criteria),
        Aggregation.group(Fields.fields("campaign_id", "city")).sum("pv").as("pv")
            .sum("uv").as("uv"),
        Aggregation.project(Fields.fields("campaign_id", "city", "pv", "uv"))
    );
    AggregationResults<OptimizationTaskStatisticsLocationDocument> statisticsLocation = mongoTemplate
        .aggregate(aggregation, "optimization_task_statistics_location",
            OptimizationTaskStatisticsLocationDocument.class);
    List<OptimizationTaskStatisticsLocationDocument> results = statisticsLocation
        .getMappedResults();
    System.out.println(aggregation.toString());
    return results;
  }

  public List getTaskStatisticsByProvinceFull(String[] id, String province) {
    Criteria criteria = new Criteria().andOperator(
        Criteria.where("campaign_id").in(id),
        Criteria.where("province").is(province));
    Aggregation aggregation = Aggregation.newAggregation(
        Aggregation.match(criteria),
        Aggregation.group(Fields.fields("campaign_id", "city")).sum("pv").as("pv")
            .sum("uv").as("uv"),
        Aggregation.project(Fields.fields("campaign_id", "city", "pv", "uv"))
    );
    AggregationResults<OptimizationTaskStatisticsLocationDocument> statisticsLocation = mongoTemplate
        .aggregate(aggregation, "optimization_task_statistics_location",
            OptimizationTaskStatisticsLocationDocument.class);
    List<OptimizationTaskStatisticsLocationDocument> results = statisticsLocation
        .getMappedResults();
    System.out.println(aggregation.toString());
    return results;
  }


  /**
   * 获取全程频控数据
   */
  public List getOptimizationTaskFullFreq(String[] id) {
    Query query = new Query();
    query.addCriteria(Criteria.where("campaign_id").in(id));
    List<OptimizationTaskFullFerStatisticsDocument> documents = mongoTemplate
        .find(query, OptimizationTaskFullFerStatisticsDocument.class);

    Map<String, OptimizationTaskFullFerStatisticsDocument> map = new HashMap<>();
    List<OptimizationTaskFullFerStatisticsDocument> list = new ArrayList<>();
    OptimizationTaskFullFerStatisticsDocument document = new OptimizationTaskFullFerStatisticsDocument();
    for (OptimizationTaskFullFerStatisticsDocument doc : documents
        ) {

      if (map.get(doc.getCampaignId()) == null) {
        doc.setTotalPv(doc.getPv());
        doc.setTotalUv(doc.getCount());
        map.put(doc.getCampaignId(), doc);
      } else {
        document = map.get(doc.getCampaignId());
        document.setTotalPv(doc.getPv() + document.getTotalPv());
        document.setTotalUv(doc.getCount() + document.getTotalUv());
        map.put(doc.getCampaignId(), document);
      }
    }

    Iterator<Entry<String, OptimizationTaskFullFerStatisticsDocument>> iterator = map.entrySet()
        .iterator();
    while (iterator.hasNext()) {
      list.add(iterator.next().getValue());
    }

    return list;
  }


  public List getTaskStatisticsByLocationFull(String id) {

    Query query = new Query();
    Criteria criteria = new Criteria().andOperator(Criteria.where("campaign_id").in(id));
    query.addCriteria(criteria);
    Aggregation aggregation = Aggregation.newAggregation(
        Aggregation.match(criteria),
        Aggregation.group(Fields.fields( "province", "campaign_id")).sum("uv").as("uv")
            .sum("pv").as("pv"),
        Aggregation.project(Fields.fields("province", "campaign_id", "pv", "uv"))
    );
    AggregationResults<OptimizationTaskStatisticsLocationFullDocument> aggregate = mongoTemplate
        .aggregate(aggregation, "optimization_task_statistics_location_full", OptimizationTaskStatisticsLocationFullDocument.class);
    List<OptimizationTaskStatisticsLocationFullDocument> locationFullDocuments =aggregate.getMappedResults();

    return locationFullDocuments;

  }
}
